package com.rpc.learn.transport.handler;

import com.rpc.learn.provider.RemoteService;
import com.rpc.learn.provider.ServiceProvider;
import com.rpc.learn.transport.dto.RpcRequest;
import com.rpc.learn.transport.exception.RemoteException;
import com.rpc.learn.transport.support.ServiceNameSupport;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

/**
 * RpcRequest processor
 *
 * @author shuang.kou
 * @createTime 2020年05月13日 09:05:00
 */
@Slf4j
public class RpcRequestHandler {
    private static final ConcurrentHashMap<String, Method> methodChcheMap = new ConcurrentHashMap<String, Method>();

    /**
     * Processing rpcRequest: call the corresponding method, and then return the method
     */
    public Object handle(RpcRequest rpcRequest) {
        String serviceName = rpcRequest.getServiceName();
        Class<?>[] paramTypes = rpcRequest.getParamTypes();
        String[] split = ServiceNameSupport.split(serviceName);
        String instantName = split[split.length - 2];
        String methodName = split[split.length - 1];
        RemoteService service = ServiceProvider.find(instantName);
        if(service == null) {
            throw new RemoteException("找不到服务实例：" + instantName);
        }
        try {
            Method method = methodChcheMap.get(serviceName);
            if(method != null) {
                return method.invoke(service, rpcRequest.getParameters());
            }
            Class<? extends RemoteService> serviceClass = service.getClass();
            method = serviceClass.getDeclaredMethod(methodName, paramTypes);
            methodChcheMap.put(serviceName, method);
            return method.invoke(service, rpcRequest.getParameters());
        } catch (NoSuchMethodException e) {
            throw new RemoteException("找不到方法", e);
        } catch (Exception e) {
            throw new RemoteException("服务调用失败", e);
        }
    }
}
